package com.powernode.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powernode.common.execption.PowerException;
import com.powernode.common.result.ResultCodeEnum;
import com.powernode.model.entity.system.SysMenu;
import com.powernode.model.entity.system.SysRoleMenu;
import com.powernode.model.vo.system.AssginMenuVo;
import com.powernode.model.vo.system.MetaVo;
import com.powernode.model.vo.system.RouterVo;
import com.powernode.system.helper.MenuHelper;
import com.powernode.system.mapper.SysMenuMapper;
import com.powernode.system.mapper.SysRoleMenuMapper;
import com.powernode.system.service.SysMenuService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {
    @Resource
    private SysMenuMapper sysMenuMapper;
    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Override
    public List<SysMenu> findNodes() {
        List<SysMenu> sysMenuList = this.list();
        if (CollectionUtils.isEmpty(sysMenuList)) return null;
        return MenuHelper.buildTree(sysMenuList);
    }

    @Override
    public boolean removeById(Serializable id) {
        long count = this.count(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getParentId, id));
        if (count > 0)
            throw new PowerException(ResultCodeEnum.NODE_ERROR);
        sysMenuMapper.deleteById(id);
        return false;
    }

    @Override
    public List<SysMenu> findSysMenuByRoleId(Long roleId) {
        List<SysMenu> allSysMenuList = this.list(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus, 1));
        List<SysRoleMenu> sysRoleMenuList = sysRoleMenuMapper.selectList(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
        List<Long> menuIdList = sysRoleMenuList.stream().map(SysRoleMenu::getMenuId).toList();
        allSysMenuList.forEach(permission -> permission.setSelect(menuIdList.contains(permission.getId())));
        return MenuHelper.buildTree(allSysMenuList);
    }

    @Transactional
    @Override
    public void doAssign(AssginMenuVo assginMenuVo) {
        sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, assginMenuVo.getRoleId()));
        for (Long menuId : assginMenuVo.getMenuIdList()) {
            if (null == menuId) continue;
            SysRoleMenu rolePermission = new SysRoleMenu();
            rolePermission.setRoleId(assginMenuVo.getRoleId());
            rolePermission.setMenuId(menuId);
            sysRoleMenuMapper.insert(rolePermission);
        }
    }

    @Override
    public List<RouterVo> findUserMenuList(Long userId) {
        List<SysMenu> sysMenuList;
        if (userId == 1)
            sysMenuList = this.list(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus, 1).orderByAsc(SysMenu::getSortValue));
        else
            sysMenuList = sysMenuMapper.findListByUserId(userId);
        List<SysMenu> sysMenuTreeList = MenuHelper.buildTree(sysMenuList);
        return this.buildMenus(sysMenuTreeList);
    }

    /**
     * 根据菜单构建路由
     */
    private List<RouterVo> buildMenus(List<SysMenu> menus) {
        List<RouterVo> routers = new LinkedList<>();
        for (SysMenu menu : menus) {
            RouterVo router = new RouterVo();
            //router.setHidden(false);
            router.setAlwaysShow(false);
            router.setPath(getRouterPath(menu));
            router.setComponent(menu.getComponent());
            Boolean isHide = menu.getIsHide() == 1;
            router.setMeta(new MetaVo(menu.getName(), menu.getIcon(), menu.getActiveMenu(), isHide));
            List<SysMenu> children = menu.getChildren();
            //如果当前是菜单，需将按钮对应的路由加载出来，如：“角色授权”按钮对应的路由在“系统管理”下面
            if (menu.getType() == 1) {
                List<SysMenu> hiddenMenuList = children.stream().filter(item -> StringUtils.hasText(item.getComponent())).toList();
                for (SysMenu hiddenMenu : hiddenMenuList) {
                    RouterVo hiddenRouter = new RouterVo();
                    //hiddenRouter.setHidden(true);
                    hiddenRouter.setAlwaysShow(false);
                    hiddenRouter.setPath(getRouterPath(hiddenMenu));
                    hiddenRouter.setComponent(hiddenMenu.getComponent());
                    Boolean isHide1 = hiddenMenu.getIsHide() == 1;
                    hiddenRouter.setMeta(new MetaVo(hiddenMenu.getName(), hiddenMenu.getIcon(), menu.getActiveMenu(), isHide1));
                    routers.add(hiddenRouter);
                }
            } else if (!CollectionUtils.isEmpty(children)) {
                router.setAlwaysShow(true);
                router.setChildren(buildMenus(children));
            }
            routers.add(router);
        }
        return routers;
    }

    /**
     * 获取路由地址
     *
     * @param menu 菜单信息
     * @return 路由地址
     */
    public String getRouterPath(SysMenu menu) {
        String routerPath = "/" + menu.getPath();
        if (menu.getParentId().intValue() != 0)
            routerPath = menu.getPath();
        return routerPath;
    }

    @Override
    public List<String> findUserPermsList(Long userId) {
        List<SysMenu> sysMenuList;
        if (userId == 1)
            sysMenuList = this.list(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus, 1));
        else
            sysMenuList = sysMenuMapper.findListByUserId(userId);
        return sysMenuList.stream().filter(item -> item.getType() == 2).map(SysMenu::getPerms).collect(Collectors.toList());
    }
}